<?php


namespace App\Http\Controllers\Api;


use App\Models\Api\Card;
use App\Models\Garbage\GarbageEvent;
use App\Models\Garbage\GarbageEventFiles;
use App\Models\Garbage\GarbageGoodInfo;
use App\Models\Garbage\GarbageGoodPurchase;
use App\Models\Garbage\GarbageInteraction;
use App\Models\Garbage\GarbagePoint;
use App\Models\Garbage\GarbageRetrieveOrder;
use App\Models\Garbage\GarbageRetrieveOrderPic;
use App\Models\SystemManagement\Manager;
use App\Http\Controllers\Controller;
use App\Models\Garbage\WeichatUser;
use App\Models\SystemManagement\User;
use SimpleSoftwareIO\QrCode\Facades\QrCode;
use http\Env\Response;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use HttpRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use mysql_xdevapi\Exception;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Validator;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
/**
 * @group 微信前端
 *
 * 采用 restful api
 *
 * Body Parameters 表示请求的所需要的参数
 *
 * Query Parameters 表示返回参数的名称
 */
class WeiController extends Controller
{

    protected $expiretime;
    protected $appid;
    protected $appse;
    protected $auth2url;
    protected $authcallback;
    protected $api;
    protected $code2openid;
    protected $token;
    protected $vToken;

    public function __construct()
    {
        $this->appid = config('weichat.appid');
        $this->appse = config('weichat.appsecret');
        $this->auth2url = config('weichat.auth2url');
        $this->authcallback = config('weichat.authcallbackurl');
        $this->api = config("weichat.weichatapi");
        $this->code2openidurl = config("weichat.code2openid");
        $this->token = config("weichat.token");
        $this->vToken = config("weicaht.validatetoken");
        $this->expiretime = config("weicaht.expiretime");
    }

    /**
     * 验证服务器接口
     */
    public function check(Request $request)
    {
        $signature = $request->get("signature");
        $timestamp = $request->get("timestamp");
        $nonce = $request->get("nonce");
        $token = $this->token;
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);
        $echoStr = $request->input("echostr");
        if ($tmpStr == $signature) {
            return response($echoStr);
        } else {
            return response("验证非法");
        }
    }
    /**
     * 接受微信post数据过来的接口
     */
    public function recv(Request $request)
    {
        $postStr = $request->getContent();
        $data = $this->xml2obj($postStr);
        $this->eventHandler($data);
    }

    /**
     * @param $data
     * xml转换成object
     */
    public function xml2obj($xml)
    {
        $obj = simplexml_load_string($xml, "SimpleXMLElement", LIBXML_NOCDATA);
        $data = json_decode(json_encode($obj), true);
        return $data;
    }

    //事件分发
    public function eventHandler($data)
    {
        Log::info(json_encode($data));

        if (array_key_exists("Event", $data)) {
            $event = $data["Event"];
            //接受订阅事件
            if ($event == "subscribe") {
                $this->subscribe($data);
            }
            //取消订阅
            if ($event == "unsubscribe") {
                $this->unsub($data);
            }
        }
        //发送消息事件的处理
        if (array_key_exists("MsgType", $data)) {
            $type = $data["MsgType"];
            if ($type == "text") {
                $this->msgText();
            }
        }
    }

    //发送消息事件处理
    public function msgText()
    {
        return True;
    }

    //取消订阅
    public function unsub($data)
    {
        $wei_user = WeichatUser::where("openid", $data["FromUserName"])->first();
        if ($wei_user) {
            $wei_user->subscribe = 0;
            $wei_user->save();
        }
    }
    //消息订阅的事件
    // 获取用户信息 创建或更新用户
    public function subscribe($data)
    {
        $openid = $data["FromUserName"];
        $userInfo = $this->getUserInfo($openid);
        unset($userInfo->language);
        unset($userInfo->unionid);
        unset($userInfo->remark);
        unset($userInfo->groupid);
        unset($userInfo->tagid_list);
        unset($userInfo->subscribe_scene);
        unset($userInfo->qr_scene);
        unset($userInfo->qr_scene_str);
        $userInfo->subscribe_time = date("Y-m-d H:i:s", $userInfo->subscribe_time);
        //更新或者创建 用户有可能以前关注过
        WeichatUser::updateOrCreate(
            array("openid" => $userInfo->openid), (array)$userInfo);
//        //如果user_id是null表示他没有指向用户 则指向用户即可
//        if ($wei_user->user_id == null) {
//            $user =User::created(['username'=>uniqid()]);
//            $user->save();
//            $wei_user->user_id = $user->id;
//            $wei_user->save();
//        }
    }


    //获取用户信息
    public function getUserInfo($openId)
    {
        $data = array(
            "access_token" => $this->getAccessCache(),
            "openid" => $openId,
        );
        $url = "{$this->api}/user/info";
        $res = $this->req($data, $url);
        return $res;

    }

    //获取access_token 存放在文件中 在1小时后过期 缓存一个小时 过了一小时就重新申请
    public function getAccessCache()
    {
        $current_hour = date("Y-m-d h:i", time());
        $fileName = sha1($current_hour) . "weixin_access_token_cache.text";
        try {
            $access_token = Storage::disk("local")->get($fileName);
        } catch (FileNotFoundException $e) {
            try {
                $access_token = $this->getAccessToken();
            }catch (FilesException $e){
                throw new FilesException($e->getMessage());
            }
            Storage::disk("local")->put($fileName, $access_token);
        }
        return $access_token;
    }


    //获取accesstoken的http接口
    public function getAccessToken()
    {
        $data = array(
            "grant_type" => "client_credential",
            "appid" => $this->appid,
            "secret" => $this->appse,
        );
        $url = "{$this->api}/token";
        $res = $this->req($data, $url);
        try{
            $access_token = $res->access_token;
            $expire = $res->expires_in;
            return $access_token;
        }catch (\Exception $e){
            throw new FileException('微信回调ip地址没有加到白名单中');
        }

    }

    //微信http请求接口
    public function req($data, $url)
    {
        $options = array(
            "http" => array(
                "method" => "GET",
                "timeout" => 60 // 超时时间（单位:s）
            )
        );
        $param = "";
        foreach ($data as $k => $v) {
            $param .= $k . "=" . $v . "&";
        }
        $param = substr($param, 0, strlen($param) - 1);
        $url = "$url?$param";
        $context = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        $data = json_decode($result);
        return $data;
    }


    /**
     * 微信公众号端商机对接用户接口 用户添加商机对接信息 POST方式
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @bodyParam code string required code
     *
     */
     function code2openId(Request $request)
     {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }

        $code = $request->get('code');
////
        $openId = $this->code2openidcurl($code);
//         $openId = $code;
        if($openId == 'error'){
            return response()->json('openid获取失败',401);
        }else{
            try {
                $user = WeichatUser::where('openid', $openId)->first()->toArray();
            }catch (\Exception $e)
            {
                return response()->json('请先关注公众号',404);
            }
            $data = ['user'=>$user,'openid'=>$openId];
            return response()->json($data,200);
        }
    }


    //通过code获取用户的openid
    function code2openidcurl($code):string
    {
        $url = "{$this->code2openidurl}?appid={$this->appid}&secret={$this->appse}&code={$code}&grant_type=authorization_code";
        //$res = $this->req([], $url);
        $options = array(
            "http" => array(
                "method" => "GET",
                "timeout" => 60 // 超时时间（单位:s）
            )
        );
        $context = stream_context_create($options);
        try{
            $result = file_get_contents($url, false, $context);
        }catch(Exception $e){
            Log::error('weichat:服务器使用code向微信服务器换取用户openid报错,网络请求失败 错误信息'.$e->getMessage());
            return 'error';
        }
        $res_arr = json_decode($result);
        try {
            $openid = $res_arr->openid;
        }catch (\Exception $e){
           Log::error("weichat:code转换openid网络请求成功,但返回信息中不包含openid信息,错误信息".$result);
           return 'error';

        }
        return $openid;
    }

    //微信http post自定义菜单接口
    function menu()
    {
        $auth = urlencode($this->authcallback);
        //每个接口都先去请求一下code 不然不知道用户的openid是多少
        $open_url = "{$this->auth2url}?appid={$this->appid}&redirect_uri={$auth}&response_type=code&scope=snsapi_base&state=-STATE-#wechat_redirect";
        //"url":"'.str_replace("-STATE-",'weichat.problem',$open_url).'"
        $jMenu = '{
        "button":[
            {	
                "name":"扫码投递",
                "sub_button": [
                    {
                        "type":"view", 
                        "name":"扫码开门", 
                        "url":"' . $open_url . '"
                    }, 
                    {
                        "type":"view", 
                        "name":"二维码投递", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/pages/QRCode/index"
                    }
                ] 
            },
            {	
                "name":"动态投递",
                "sub_button": [
                    {
                        "type":"view", 
                        "name":"政务服务", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/"
                    }, 
                    {
                        "type":"view", 
                        "name":"分类学堂", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/"
                    },
                    {
                        "type":"view", 
                        "name":"最新资讯", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/pages/news/index"
                    }
                ] 
            },
            {	
                "name":"会员专区",
                "sub_button":[
                    {
                        "type":"view", 
                        "name":"商机对接", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/pages/cooperation/index"
                    }, 
                    {
                        "type":"view", 
                        "name":"客户中心", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/"
                    },
                    {
                        "type":"view", 
                        "name":"积分兑换", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/pages/mine/integral/index"
                    },
                    {
                        "type":"view", 
                        "name":"会员主页", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/"
                    },
                    {
                        "type":"view", 
                        "name":"大件回收", 
                        "url":"http://xtuugzh.hk.southmeteor.com:801/#/pages/mine/bulkRecovery/index"
                    },
                ] 
            }
        ]
        }';

        $url = "{$this->api}/menu/create";
        $token = $this->getAccessCache();
        $url = "$url?access_token=$token";
        $result = $this->postcurl($url, $jMenu);
        return response()->json($result);
    }


    function postcurl($url, $data = null)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($ch, CURLOPT_POST, TRUE);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output = json_decode($output, true);
    }

    function file()
    {
        $file = 'MP_verify_qgW9bhl7h88RN5ez.txt';
        //判断文件是否存在
        return response()->download(storage_path($file));
    }

    //生成自己的token 根据openid 过期时间 生成一个token
    function genToken(string $openid,int $expireTimeStamp):string
    {
        $token = $this->genSecret($openid.$expireTimeStamp);
        return $token;
    }
    //验证token 根据openid 过期时间 验证一个token是否有效
    function validateToken($openid,$expireTimeStamp,$token)
    {
        if(($expireTimeStamp - $this->expiretime) < time()){
            return false;
        }
        $is_vali = $this->valiSecret($openid.$expireTimeStamp,$token);
        return $is_vali;
    }

    function genSecret($str){
        return sha1($str.$this->vToken);
    }

    function valiSecret($str,$token){
        Log::info(sha1($str.$this->vToken));
        return sha1($str.$this->vToken) == $token;
    }

    //通过openid取出用户信息
    function openid2userid(string $openid)
    {
        Log::info("sql {$openid}");
        $weichat_user = WeichatUser::where("openid",$openid)->get();
        $data = $weichat_user->toArray();
        //没有返回0
        if($data == []){
            return 0;
        }
        return  $data[0]['id'];

    }
    /**
     * 微信公众号端商机对接用户接口 用户添加商机对接信息 POST方式
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     * @bodyParam phone string required 用户预留手机号
     * @bodyParam name string required 用户预留称呼
     * @bodyParam desc string required 预留信息
     * @bodyParam gender int required 性别
     * @bodyParam email string required 邮箱
     *
     */

    function problems(Request $request){
        //$data = route('weichat.problem');
//        $validator = Validator::make($request->all(),genValidate());
//        if($validator->fails()){
//            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
//        }
        //验证openid
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        //通过openid获取出用户信息
//        $user_id = $this->openid2userid($request->get('openid'));
//        if($user_id == 0){
//            return response()->json(encodeMsg(["message" => "数据库无此openid对应的用户"],404), 404);
//        }
        $user_id = $request->user_id;
        $create_data = [];
        foreach ($request->all() as $k=>$v){
            if(in_array($k, array('user_id','desc','name','phone','email')))
                $create_data[$k] = $v;
        }
        $create_data['no'] = getRandNumber();
        $create_data['status'] = 1;
        $create_data['user_id'] = $user_id;
        $problem = GarbageInteraction::create($create_data);
        try {
            $data = $problem->save();
            if($data){
                return response()->json(encodeMsg($problem,201), 201);
            }else{
                return response()->json(encodeMsg(["message" => "添加失败"],500), 500);
            }

        } catch (QueryException $e) {
            return response()->json(encodeMsg(["message" => $e->getMessage()],500), 500);
        }
    }

    /**
     * 垃圾分类->问题反馈->后台发送积分或红包 给微信用户接口 注意 这是后台的接口
     * 调用该接口会发送信息给用户
     *
     * @bodyParam value float required 发送的数额
     * @bodyParam type int required 发送的类型(1. 积分 2. 红包) 目前只填写 1
     * @bodyParam event string required 基于什么事件发送积分  比如垃圾回收奖励的和执法管理奖励的 让他们自己填
     * @bodyParam event_id int required 对应问题反馈的问题id号
     */
    function pointPost(Request $request)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }
        $event = GarbageEvent::find($request->get('event_id'));
        $user = WeichatUser::find($event->user_id);
        if($user == []){
            return response()->json(encodeMsg(["message" =>'该用户不存在'],400), 400);
        }

        if($event == []){
            return response()->json(encodeMsg(["message" =>'该用问题事件不存在'],400), 400);
        }

        if($event->is_reward){
            return response()->json(encodeMsg(["message" =>'已经发过奖励了'],400), 400);
        }

        $type = $request->get('type');//重要 需要根据type来看发送积分还是红包
        //消息发送完成后 发送奖励
        $event_point = $request->get("value");
        $p = new GarbagePoint();
        $p->event_point = $event_point;
        $p->user_id = $user->id;
        $p->event = $request->get('event');
        $p->kind = 3;
        $user_point = $user->point;
        $final_point = $user_point + $event_point;
        $p->final_point=$final_point;
        $p->no = genOrderNumber();
        //更新问题反馈的列表信息
        $event->reward = $event_point;
        $event->reward_type = $type;
        $event->is_reward = 1;
        $is_recall = $event->is_recall;//读取是否回复问题反馈通知
        if($final_point < 0){
            return response()->json(encodeMsg(["message" =>'变更后用户积分为负 不能变更'],400), 400);
        }
        if($event_point>0) {
           $user->accumulation_point = $user->accumulation_point + $event_point;

        }
        $user->point=$final_point;
        //积分发送
        DB::beginTransaction();
        try {
            $user->save(); $p->save();
            $event->save();

            Log::info("向id号为{$user->id}的用户发送了{$event_point}积分");
            try {
                //如果用户选择通知用户反馈 则调用微信接口通知
                $is_recall && $this->sendPointWeichat($user, $event_point, $event->title);
            }catch (FilesException $e){
                DB::rollBack();
                return response()->json(encodeMsg($e->getMessage(),500), 500);
            }
            DB::commit();
            return response()->json(encodeMsg($p,201), 201);
        }catch (\Exception $e){
            DB::rollback();
            return response()->json(encodeMsg(["message" =>$e->getMessage()],500), 500);
        }

    }

    //发送api指令 向用户发送积分
    function sendPointWeichat($user,$point,$event)
    {
        $msg = '{
            "touser":"'.$user->openid.'",
            "msgtype":"text",
            "text":
            {
                "content":"亲爱的用户'.$user->nickname.'由于你提交的事件'.$event.'奖励'.$point.'积分,请领取"
            }
        }';
        //向用户发送消息
        $url = "{$this->api}/message/custom/send?access_token={$this->getAccessCache()}";
        try{
            $res = $this->postcurl($url,$msg);
        }catch (\Exception $e){
            throw new FilesException('网络请求失败,无法连接到微信');
            return;
        }
        if($res['errcode'] === 0){
            return;
        } else{
            throw new FilesException('接口请求失败,微信无法发送消息'.$res['errmsg']);
            return;
        }
    }


    function test(Request $request)
    {
        //Log::info($request->getRequestUri());
        //Log::info(json_encode($request));

        //$this->code2openid($request->get('code'));
        return $this->openid2user('aaabbb');
    }

    /**
     * 用户点击公众号的按钮之后 所有的接口都会在这里来
     * 这个接口的作用是通过code 把code转换成user的openid 然后再把这个再根据微信那边提交过来的
     * state 找到合适的接口 发送给前端 前端再把数据带上回到其他的接口
     */
    function authRedirect(Request $request)
    {

        if(!$request->has('code')){
            Log::error('weichat:微信回调接口(authredirect)错误,微信未回传code参数');
            return response()->json([],400);
        }

        if(!$request->has('state')){
            Log::error('weichat:微信回调接口(authredirect)错误,微信未回传state参数');
            return response()->json([],400);
        }

        $openid = $this->code2openid($request->get('code'));

        if($openid === 'error'){
            return \response()->json(encodeMsg(['message'=>'openid获取失败,请联系管理员'],500),500);
        }
        $userId =  $this->openid2userid($openid);
        Log::info($userId);
        if($userId === 0){
            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
        }
        //state参数对应的是url的名称 可以直接通过这个来获取到url,在测试的时候 把这个返给用户
        try {
            $url = route($request->get('state'));
        }catch (Exception $e){
            Log::error('weichat:出现出发回调的state地址 无法换算为api接口调用 state的值为'.$request->get('state'));
            return \response()->json(encodeMsg(['message'=>'非法回调地址'],404),404);
        }

        //为前端页面生成 token openid两个参数 通过get回调前端页面传递给前端
        $expire = time() + $this->expiretime;
        $token = $this->genToken($openid,$expire);
        $redirect_url = $url."?token={$token}&openid={$openid}&expire=$expire";
        Log::info($redirect_url);
        return response($redirect_url);
    }

    function webToken(Request $request){
        $openid = $request->get('openid');
        $expire = time() + $this->expiretime;
        $token = $this->genToken($openid,$expire);
        $redirect_url = "token={$token}&openid={$openid}&expire=$expire";
        Log::info($redirect_url);
        return response($redirect_url);
    }

    /**
     * 微信公众号端 用户添加大件订单信息 POST方式
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam no 订单编号
     * @queryParam user_id 订单用户id号
     * @queryParam price 回收价格
     * @queryParam address 回收地址
     * @queryParam status 状态 1待取货 2已取货
     * @queryParam start_time 预约回收起始时间
     * @queryParam end_time 预约回收结束时间
     * @queryParam weight 回收物重量
     * @queryParam desc 备注信息
     * @queryParam is_retrieve 是否已取货
     * @queryParam name 用户预留名称
     * @queryParam phone 用户预留手机
     * @queryParam user->nickname 用户微信昵称
     * @queryParam user->openid 用户微信号
     * @queryParam kind->name 回收物品
     * @queryParam images 回收图片
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     * @bodyParam name string required 昵称
     * @bodyParam phone string required 手机号
     * @bodyParam address string required 回收地址
     * @bodyParam start_time timestamp required 预约回收起始时间
     * @bodyParam end_time timestamp required 预约回收结束时间
     * @bodyParam weight float required 回收物重量
     * @bodyParam desc string required 备注信息
     * @bodyParam kind_id int required 物件类信息
     * @bodyParam files string optional 订单回收相关文件id串 如果只有一个文件 上传 1 如果多个 使用逗号隔开 1,2,3,4,5 特别注图片id必须是已经调用图片接口添加好了的
     */

    public function recycle(Request $request)
    {
//        $validator = Validator::make($request->all(),genValidate());
//        if($validator->fails()){
//            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
//        }

//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $insert_data = array('no'=>uniqid());
        $post_data =$request->all();
        if($request->has('no'))
            unset($post_data['no']);
        $insert_data = array_merge($insert_data,$post_data);
        $insert_data = array_merge($insert_data,array('user_id'=>$userId));
        DB::beginTransaction();
        try {
            $data = GarbageRetrieveOrder::create($insert_data);
        }catch (\Exception $e){
            DB::rollBack();
            return response()->json(encodeMsg(["message" => "请确认回收物分类信息是否正确"],404), 404);
        }
        if($request->has('files')){
            $file_data = [];
            $fileArr = explode(',',$request->get('files'));
            foreach ($fileArr as $k=>$value){
                $tmp = [];
                $tmp['file_id'] = $value;
                $tmp['order_id'] = $data->id;
                array_push($file_data,$tmp);
            }
            try{
                GarbageRetrieveOrderPic::insert($file_data);
            }catch (\Exception $e){
                DB::rollBack();
                return response()->json(encodeMsg(["message" => "请先确认图片是否已经添加"],404), 404);
            }

        }
        DB::commit();
        return response()->json(encodeMsg($data,200), 201);
    }


    /**
     * 微信公众号端->大件回收预约->我的回收 get方式
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam no 订单编号
     * @queryParam user_id 订单用户id号
     * @queryParam price 回收价格
     * @queryParam address 回收地址
     * @queryParam status 状态 1待取货 2已取货 3.回收成功 4. 回收失败
     * @queryParam start_time 预约回收起始时间
     * @queryParam end_time 预约回收结束时间
     * @queryParam weight 回收物重量
     * @queryParam desc 备注信息
     * @queryParam is_retrieve 是否已取货
     * @queryParam name 用户预留名称
     * @queryParam phone 用户预留手机
     * @queryParam user->nickname 用户微信昵称
     * @queryParam user->openid 用户微信号
     * @queryParam kind->name 回收物品
     * @queryParam images 回收图片
     * @queryParam updated_at 如果有回收成功或失败的状态 显示这个时间
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     */

    public function recycleList(Request $request)
    {
//        $validator = Validator::make($request->all(),genValidate());
//        if($validator->fails()){
//            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
//        }
//
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }

//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $data = GarbageRetrieveOrder::where('user_id',$userId);
        return response()->json(encodeMsg($data->paginate(),200), 201);
    }

    /**
     * 微信公众号端->大件回收预约->回收详情  get方式 用户无法查看不属于自己的订单
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam no 订单编号
     * @queryParam user_id 订单用户id号
     * @queryParam price 回收价格
     * @queryParam address 回收地址
     * @queryParam status 状态 1待取货 2已取货 3.回收成功 4. 回收失败
     * @queryParam start_time 预约回收起始时间
     * @queryParam end_time 预约回收结束时间
     * @queryParam weight 回收物重量
     * @queryParam desc 备注信息
     * @queryParam is_retrieve 是否已取货
     * @queryParam name 用户预留名称
     * @queryParam phone 用户预留手机
     * @queryParam user->nickname 用户微信昵称
     * @queryParam user->openid 用户微信号
     * @queryParam kind->name 回收物品
     * @queryParam images 回收图片
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     */

    public function recycleDetail(Request $request,$pk)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }
//
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }

//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
//        $data = GarbageRetrieveOrder::with('images')->with('user')->with('kind')->where('user_id',$userId)->find($pk);
//        return response()->json(encodeMsg($data,200), 201);
    }


    /**
     * 微信公众号端->兑换商城->商品列表
     * @bodyParam garbage_good_kind_id int optional 筛选商品分类
     * @bodyParam city_id int optional 筛选商品地区
     * @bodyParam search string optional 搜索商品名称(模糊查询)
     *
     * @queryParam garbage_good_kind_id 所属分类
     * @queryParam name 商品名称
     * @queryParam city_id 所属城市
     * @queryParam price 所属城市价格
     * @queryParam point 所属城市积分
     * @queryParam desc 商品介绍
     * @queryParam on_sale 是否上架
     * @queryParam file_id 商品图片id
     * @queryParam store 商品库存
     * @queryParam exchanges_count 已经有多少人购买
     */
    public function good(Request $request)
    {
        $query = GarbageGoodInfo::withCount('exchanges')->with('kind')->with('files')->with('city');
        $query->where(function ($q) use ($request){
            $request->has('garbage_good_kind_id') && $q->where('garbage_good_kind_id','=',$request->get('garbage_good_kind_id'));
            $request->has('city_id') && $q->where('city_id','=',$request->get('city_id'));
            $request->has('search') && $q->where('name','LIKE',"%{$request->get('search')}%");
        });

        return response()->json(encodeMsg($query->paginate(),200),200);
    }


    /**
     * 微信公众号端->兑换商城->商品详情
     *
     * @queryParam garbage_good_kind_id 所属分类
     * @queryParam name 商品名称
     * @queryParam city_id 所属城市
     * @queryParam price 所属城市价格
     * @queryParam point 所属城市积分
     * @queryParam desc 商品介绍
     * @queryParam on_sale 是否上架
     * @queryParam file_id 商品图片id
     * @queryParam store 商品库存
     */
    public function goodDetail(Request $request,$pk)
    {
        $query = GarbageGoodInfo::with('kind')->with('files')->with('city')->find($pk);
        return response()->json(encodeMsg($query, 200), 200);

    }
     /**
     * 微信公众号端->兑换商城->商品立刻兑换
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     * @bodyParam good_id int required 兑换商品id号
     * @bodyParam good_num int optional 兑换商品数量 默认1个
     */
    public function purchase(Request $request){

        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }

//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $good = GarbageGoodInfo::find($request->get('good_id'));
        if($good == []){
            return response()->json(encodeMsg(["message" => "系统中没有该商品的id号 请确认"],404), 404);
        }
        //获取购买商品的数量
        $request->has('good_num')?$good_num=$request->get('good_num'):$good_num = 1;
        $store = $good->store;
        //验证库存和积分
        if($store - $good_num < 0){
            return response()->json(encodeMsg(["message" => "商品库存数量不足,只能购买{$store}个"],404), 404);
        }
        $user = WeichatUser::find($userId);
        $point = $user->point;
        if(($point - $good_num * $good->point) < 0){
            return response()->json(encodeMsg(["message" => "你的积分不足,剩余积分{$user->point}"],404), 404);
        }
        //开始执行购买商品逻辑 增加积分兑换记录表 扣除用户表的积分 扣除商品库存 增加用户积分变动表
        $purchase_point =$good_num * $good->point;
        $event_point = ($purchase_point)*-1;
        $good->store = $good->store - $good_num;
        //新增用户积分变动表 //并且变动用户积分
        $p = new GarbagePoint();
        $p->event_point = $event_point;
        $p->user_id = $user->id;
        $p->event = "积分兑换商品:{$good->name}数量:{$good_num}";
        $user_point = $user->point;
        $final_point = $user_point + $event_point;
        $p->final_point=$final_point;
        $user->point=$final_point;
        $p->no = genOrderNumber();
        $p->kind = 1;
        $purchase = new GarbageGoodPurchase();
        $purchase->point = $purchase_point;
        $purchase->good_id = $good->id;
        $purchase->code = uniqid();
        $purchase->num = $good_num;
        $purchase->user_id = $userId;
        DB::beginTransaction();
        try {
            $p->save();
            $user->save();
            $good->save();
            $purchase->change_id = $p->id;
            $purchase->save();
            DB::commit();
            return response()->json(encodeMsg($purchase, 201), 201);
        }catch (\Exception $e){
            DB::rollback();
            return response()->json(encodeMsg(["message" => "服务器错误{$e->getMessage()}"],500), 500);
        }
    }

         /**
          * 微信公众号端->我的订单   注意购买商品的之后 有购买时间和兑换时间 两个是不一样的
          * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
          *
          * @queryParam point 兑换的积分
          * @queryParam created_at 购买时间
          * @queryParam exchange_time 购买商品之后的兑换时间 默认null 因为购买了之后还没去现场兑换商品
          * @queryParam good_id 购买商品的id号
          * @queryParam exchange 是否兑换 0未兑换 1已兑换
          * @queryParam code 兑换码
          * @queryParam num 购买数量
          * @queryParam change_id 积分详情表对应的id号
          * @queryParam goods->name 商品名称
          * @queryParam goods->desc 商品详情 应该是规格 没看到其他字段
          * @queryParam goods->files 商品图片
          *
          * @bodyParam openid string optional 用户的openid
          * @bodyParam expire int optional 时间戳
          * @bodyParam token string optional token值
          * */
    function userOrders(Request $request)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }

//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $query = GarbageGoodPurchase::with('goods')->where('user_id',$userId);
        return response()->json(encodeMsg($query->paginate(), 200), 200);
    }


    /**
     * 微信公众号端->我的订单->订单删除功能 用户只能删除自己的订单
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     *
     * */
    function userOrdersDelete(Request $request,$pk)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }

        $userId = $request->user_id;
        $data = GarbageGoodPurchase::where('user_id',$userId)->find($pk);
        if($data == []){
            \response()->json(encodeMsg(['message'=>'没有该订单信息 无法删除'],404),404);
        }
        try{
            $data->delete();
            return response()->json(encodeMsg(["message"=>"删除成功"],200),200);
        }catch (\Exception $e){
            return response()->json(encodeMsg(["message"=>"服务器错误 无法删除{$e->getMessage()}"],500),500);
        }
    }


    /**
     * 微信公众号端->积分明细 用户查看自己的积分明细 如果用户没有兑换这个商品 那么就点不开箭头右边商品的详情
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam event_point 本次消费的积分
     * @queryParam good_purchase->exchange_time 兑换时间 有可能没兑换
     * @queryParam good_purchase->id 兑换流水号
     * @queryParam good_purchase->goods->name 商品名称
     * @queryParam good_purchase->goods->files 商品图片信息
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     *
     * */
    function userPoints(Request $request)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }

//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }

        $userId = $request->user_id;
        $data = GarbagePoint::with('goodPurchase')->where('user_id',$userId)->where('kind',1);
        return response()->json(encodeMsg($data->paginate(),200),200);
    }


    /**
     * 微信公众号端->绑定卡号 输入卡号密码 绑定卡号
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam card string 成功后可以看到卡号在用户card字段中
     *
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     * @bodyParam card string required 卡号.
     * @bodyParam pwd string required 密码
     *
     * */
    function userCards(Request $request)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $user = WeichatUser::find($userId);
        if($user->card){
            return \response()->json(encodeMsg(['message'=>'已经绑定卡号'],404),404);
        }
        $card = Card::where('card',$request->get('card'))->where('pwd',$request->get('pwd'))->get();
        if($card == [])
        {
            return \response()->json(encodeMsg(['message'=>'卡密错误无法绑定'],404),404);
        }
        $user->card = $request->get('card');
        return response()->json(encodeMsg($user,200),200);
    }



    /**
     * 微信公众号端->政务服务 问题反馈的提交接口
     *
     * @queryParam title  反馈标题.
     * @queryParam desc 内容提要.
     * @queryParam user_id  反馈人.
     * @queryParam admin_id  负责人.
     * @queryParam area_id  地区.
     * @queryParam address  详细地址.
     * @queryParam status  状态. 1已反馈 2 已处理 3 处理中 4. 待处理
     *
     *
     * @bodyParam title string required 标题
     * @bodyParam desc string required 内容提要.
     * @bodyParam area_id int optional 地区
     * @bodyParam address string optional 详细地址.
     * @bodyParam anonymous bool optional 是否匿名 默认0 不匿名
     * @bodyParam is_recall bool optional 反馈时发送消息通知 默认 1 发送
     * @bodyParam files string optional 订单回收相关文件id串 如果只有一个文件 上传 1 如果多个 使用逗号隔开 1,2,3,4,5 特别注图片id必须是已经调用图片接口添加好了的
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     */

    public function eventPost(Request $request)
    {
        $validator = Validator::make($request->all(),genValidate());
        if($validator->fails()){
            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
        }

//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;

        $insertData = $request->all();
        $insertData['user_id'] = $userId;
        $data = GarbageEvent::create($insertData);
        if($request->has('files')){
            $file_data = [];
            $fileArr = explode(',',$request->get('files'));
            foreach ($fileArr as $k=>$value){
                $tmp = [];
                $tmp['file_id'] = $value;
                $tmp['event_id'] = $data->id;
                array_push($file_data,$tmp);
            }
            try{
                GarbageEventFiles::insert($file_data);
            }catch (\Exception $e){
                return response()->json(encodeMsg(["message" => "请先确认图片是否已经添加"],404), 404);
            }

        }
        return response()->json(encodeMsg($data,201), 201);
    }


    /**
     * 微信公众号端->用户信息
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @queryParam point 当前积分
     * @queryParam accumulation_point 累计积分
     * @queryParam nickname 昵称
     * @queryParam level 用户等级
     * */
    function userInfo(Request $request)
    {
//        $validator = Validator::make($request->all(),genValidate());
//        if($validator->fails()){
//            return response()->json(encodeMsg($validator->errors()->messages(),400),400);
//        }
//        if(!$this->validateToken($request->get('openid'),$request->get('expire'),$request->get('token'))){
//            return response()->json(encodeMsg(["message" => "token验证失败或过期"],400), 400);
//        }
//        $userId =  $this->openid2userid($request->get('openid'));
//        if($userId === 0){
//            return \response()->json(encodeMsg(['message'=>'系统暂无此用户,该用户可能并未关注公众号'],404),404);
//        }
        $userId = $request->user_id;
        $user = WeichatUser::find($userId);
        return response()->json(encodeMsg($user,200),200);
    }

    /**
     * 微信公众号端->商品购买二维码生成
     * openid expire token是上一步后台回调前端页面带上的参数 原封不对带回来即可
     *
     * @bodyParam code string require 兑换码
     * @bodyParam openid string optional 用户的openid
     * @bodyParam expire int optional 时间戳
     * @bodyParam token string optional token值
     * */

    function genCode(Request $request){
        $userId = $request->user_id;
        $param = generateToken(40);
        $qrcode = "data:image/png;base64,".base64_encode(QrCode::format('png')->size(400)->generate('http://www.baidu.com/'.$param));//网址为手机端授权登录页面地址
        $data['code'] = $param;
        $data['qrcode'] = $qrcode;
        return response()->json(encodeMsg($data, 200));
    }

    function scan(Request $request)
    {
        $url = $request->input('url','无url输入');
        $p = new JSSDK($this->appid,$this->appse,$url);
        $package = $p->getSignPackage();
        return response()->json(encodeMsg($package, 200));
    }
}
